﻿using System;
using System.Globalization;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;
using SAIM.Models;
using SAIM.Models.DAL;
using SAIM.Models.BLL;
using System.Text.RegularExpressions;
using System.Collections.Generic;

namespace SAIM.Controllers
{
    [Authorize]
    public class UsersController : Controller
    {
        private SAIMIdentity UserIdentity
        {
            get { return new SAIMIdentity(User.Identity); }
        }

        public enum UsersMessageId
        {
            AddUserSucces,
            ChangePasswordSuccess,
            ChangeProfileSuccess,
            RemoveUserPetitionSuccess
        }

        //
        // GET: /Users/Search
        public ActionResult Search()
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                // Validación de privilegios de usuario (Roles)
                if (user.isInRole("Search users"))
                {
                    return View();
                }
                else
                {
                    throw new HttpException(403, "Access Denied");
                }
            }
        }

        /// <summary>
        /// ## Vista Parcial ##
        /// Muestra todos los usuarios que comienzan con un Id o nombre en específico
        /// </summary>
        /// <param name="RPE">Id de usuario</param>
        /// <param name="Name">Nombre de usuario</param>
        /// <returns></returns>
        public ActionResult _Get(string RPE, string Name)
        {
            var users = AspNetUsersBLL.FindUser(RPE, Name);
            _GetViewModel model = new _GetViewModel(users);

            return PartialView(model);
        }
        
        //
        // GET: /Users/Manage
        public ActionResult Manage(string id, UsersMessageId? message)
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                // Validación de privilegios de usuario (Roles)
                if (user.isInRole("Search users"))
                {
                    if (id == null)
                        return RedirectToAction("Index", "Manage");
                    else
                    {
                        // Obtención de usuario mediante Id
                        using (AspNetUsersBLL newUser = new AspNetUsersBLL(id))
                        {
                            ViewBag.StatusMessage =
                            message == UsersMessageId.ChangePasswordSuccess ? "Contraseña cambiada correctamente." :
                            message == UsersMessageId.ChangeProfileSuccess ? "Perfil asignado correctamente." : "";
                            UserManageViewModel model = new UserManageViewModel(newUser.Value);
                            return View(model);
                        }
                    }
                }
                else
                {
                    throw new HttpException(403, "Access Denied");
                }
            }
        }

        //GET Users/Roles
        public ActionResult Roles(string id)
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                // Validación de privilegios de usuario (Roles)
                if (user.isInRole("Search users"))
                {
                    if (id == null)
                        return RedirectToAction("Index", "Manage");
                    else
                    {
                        // Obtención de usuario mediante Id
                        using (AspNetUsersBLL newUser = new AspNetUsersBLL(id))
                        {
                            RolesUsersViewModel model = new RolesUsersViewModel(newUser.Value);
                            return View(model);
                        }
                    }
                }
                else
                {
                    throw new HttpException(403, "Access Denied");
                }
            }
        }

        //POST Users/Roles, Aqui ingresa cuando se crea un nuevo rol para un usuario
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Roles(RolesUsersViewModel model)
        {
            using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                // Validación de privilegios de usuario (Roles)
                if (user.isInRole("Search users"))
                {
                    if (ModelState.IsValid)
                    {
                        // Obtención de usuario mediante Id
                        using (AspNetUsersBLL newUser = new AspNetUsersBLL(model.Id))
                        {
                            if (!model.RemoveRole)
                            {
                                if (!newUser.SetRole(model.NewRole))
                                    ModelState.AddModelError("", "No se pudó agregar el nuevo rol");
                                else
                                    ViewBag.StatusMessage = "Rol agregado exitosamente";
                                RolesUsersViewModel newModel = new RolesUsersViewModel(newUser.Value);
                                return View(newModel);
                            }
                            else
                            {
                                if (!newUser.RemoveRole(model.NewRole))
                                ModelState.AddModelError("", "No se puede eliminar el rol");
                                else
                                    ViewBag.StatusMessage = "Rol eliminado exitosamente";
                                RolesUsersViewModel newModel = new RolesUsersViewModel(newUser.Value);
                                return View(newModel);
                            }
                        }
                    }
                    else
                    {
                        throw new HttpException(403, "Too Few Arguments");
                    }
                }
                else
                {
                    throw new HttpException(403, "Access Denied");
                }
            }
        }

        //GET Users/ChangeProfile
        public ActionResult ChangeProfile(string id)
        {
            using (AspNetUsersBLL userAdmin = new AspNetUsersBLL(UserIdentity.GetUserId()))
            {
                // Validación de privilegios de usuario (Roles)
                if (userAdmin.isInRole("Search users"))
                {
                    using (AspNetUsersBLL user = new AspNetUsersBLL(id))
                    {
                        UserChangeProfileViewModel model = new UserChangeProfileViewModel()
                        {
                            Id = id,
                            Email = UserIdentity.GetUserEmail(),
                            UserName = UserIdentity.GetUserName(),
                            ProfileName = user.Value.AspNetProfiles != null ? user.Value.AspNetProfiles.Name : string.Empty
                        };
                        return View(model);
                    }
                }
                else
                {
                    throw new HttpException(403, "Access Denied");
                }
            }
        }

        //
        // POST: /Users/ChangeProfile
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ChangeProfile(UserChangeProfileViewModel model)
        {
            // Validación del modelo
            if (ModelState.IsValid)
            {
                using (AspNetUsersBLL user = new AspNetUsersBLL(UserIdentity.GetUserId()))
                {
                    // Validación de privilegios de usuario (Roles)
                    if (user.isInRole("Search users"))
                    {
                        // Obtención de usuario por Id(RPE)
                        using (AspNetUsersBLL userToUpdate = new AspNetUsersBLL(model.Id))
                        {
                            // Establecimiento de nuevo perfil de usuario
                            bool succes = userToUpdate.setProfile(model.Profile);
                            if (succes)
                                return Redirect("Manage/?id=" + model.Id + "&message=ChangeProfileSuccess");
                        }
                    }
                    else
                    {
                        throw new HttpException(403, "Access Denied");
                    }
                }
            }
            ModelState.AddModelError("", "No se pudo establecer el perfil. Por favor intente más tarde.");
            return View(model);
        }

        [HttpPost]
        public ActionResult NotificationsCount()
        {
            Random rnd = new Random();

            using(NotificationsBLL notification = new NotificationsBLL())
            {
                return new JsonResult() { Data = notification.GetUserNotifications(UserIdentity.GetUserId()) };
            }
        }

        [HttpPost]
        public ActionResult GetUserNotifications(int current, int rowCount, Dictionary<object, string> sort, string searchPhrase)
        {
            int _current = current;
            int _rowCount = rowCount;
            int _total = 0;

            using (NotificationsBLL notification = new NotificationsBLL())
            {
                return new JsonResult()
                {
                    Data = new NotificationGridData(notification.GetUserNotifications(UserIdentity.GetUserId(), ref _current, _rowCount, ref _total))
                    {
                        current = _current,
                        rowCount = _rowCount,
                        total = _total
                    }
                };
            }
        }

        public JsonResult GetTypeaheadUsers(string id)
        {
            var users = AspNetUsersBLL.FindTypeaheadUsers(id);

            return Json(users, JsonRequestBehavior.AllowGet);
        }
    }
}